﻿using System;
using System.Collections.Generic;
using System.Windows.Browser;
using System.Windows.Input;
using Microsoft.Practices.Unity;
using Refract.Views;
using Microsoft.Practices.Unity.Utility;

namespace Refract.Navigation
{
    /// <summary>
    /// Provides page navigation functionality
    /// </summary>
    public class Navigator : INavigator
    {
        #region Fields

        private PageItemList _PageItems = new PageItemList();
        private ViewModel _activeViewModel;
        private string _mainRegionName;

        #endregion           

        #region Properties

        /// <summary>
        /// Gets the page items.
        /// </summary>
        /// <value>The page items.</value>
        public PageItemList PageItems { get { return _PageItems; } }

        /// <summary>
        /// Gets or sets the container.
        /// </summary>
        /// <value>The container.</value>
        [Dependency]
        public IUnityContainer Container { get; set; }

        [Dependency]
        public IHtmlContext Html { get; set; }

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="Navigator"/> class.
        /// </summary>
        /// <param name="mainRegionName">Name of the main region.</param>
        public Navigator(string mainRegionName)
        {
            _mainRegionName = mainRegionName;
            PageItems.OnNavigate += new EventHandler<EventArgs<string>>(PageItems_OnNavigate);

        }

        void PageItems_OnNavigate(object sender, EventArgs<string> e)
        {
            Goto(e.Data);
        }

        #endregion

        #region Public

        /// <summary>
        /// Registers a page.
        /// </summary>
        /// <typeparam name="TViewModel">The type of the view model.</typeparam>
        /// <param name="pageName">Name of the page.</param>
        /// <param name="targetComand">The target comand.</param>
        /// <returns></returns>
        public INavigator RegisterPage<TViewModel>(string pageName) where TViewModel : ViewModel
        {
            return RegisterPage(pageName, typeof(TViewModel));
        }

        /// <summary>
        /// Registers a page.
        /// </summary>
        /// <param name="pageName">Name of the page.</param>
        /// <param name="viewModelType">Type of the view model.</param>
        /// <param name="targetComand">The target comand.</param>
        /// <returns></returns>
        public INavigator RegisterPage(string pageName, Type viewModelType)
        {
            PageItem pageItem = new PageItem(pageName, viewModelType);
            _PageItems.Add(pageItem);
            Container.RegisterType(viewModelType);
            if (pageName == Html.CurrentBookmark)
            {
                Goto(pageName);
            }

            return this;
        }
        

        /// <summary>
        /// Goes to the specified page.
        /// </summary>
        /// <param name="pageName">Name of the page.</param>
        public void Goto(string pageName)
        {
            Guard.ArgumentNotNullOrEmpty(pageName, "pageName");

            PageItem navigatedPage = _PageItems[pageName];

            if (navigatedPage == null)
            {
                throw new KeyNotFoundException("Page " + pageName + " not found in page list.");
            }
            Clear();

            ViewModel viewModel = Container.Resolve(navigatedPage.ViewModelType) as ViewModel;
            viewModel.Show(_mainRegionName);
            _activeViewModel = viewModel;
            Html.NavigateToBookmark(pageName);
            

        }
        
        /// <summary>
        /// Closes any active page.
        /// </summary>
        public void Clear()
        {
            if (_activeViewModel != null)
            {
                _activeViewModel.Close();
                _activeViewModel = null;
            }

        } 

        #endregion
    }
}
